import { install } from "./install"
import Vue from 'vue'

export type I18nOptions = {
    locale?: string;
    messages?: any;
}

/**
 * 
 */
export default class VueI18n {
    static install
    public locale
    private messages
    private _vm: Vue
    private _dataListeners: Set<any>
    constructor(options: I18nOptions = {}) {

        const locale = options.locale ?? 'en-US'
        const messages = options.messages ?? {}
        this.locale = locale
        this.messages = messages

        this._dataListeners = new Set()

        this._vm = this._initVM({
            locale,
            // messages
        })

        this.watchI18nData()

        this.watchLocale()
    }

    /**
     * - 监听 vm.$i18n.locale
     * - 同步改动到 $i18n 内部的 vue 实例
     * - 触发该 vue 实例的侦听器
     * - 侦听器回调
     */
    watchLocale() {
        Object.defineProperty(this, "locale", {
            set: (newVal) => {
                console.log('set', newVal)
                this._vm.$data.locale = newVal
            },
            get: () => {
                return this._vm.$data.locale
            }
        })
    }


    /**
     * 
     * i18n 实例上 创建一个 vue 实例。
     * 
     */
    _initVM(data: I18nOptions) {
        return new Vue({ data })
    }

    // 收集使用的组件
    subscribeDataChanging(vm: any): void {
        this._dataListeners.add(vm)
    }

    unsubscribeDataChanging(vm: any): void {
        this._dataListeners.delete(vm)
    }

    /**
     * locale 变化的时候，强制所有使用过 $t 的组件更新，即重新触发 $t 函数，动态切换语言原理？
     */
    watchI18nData() {
        return this._vm.$watch('$data', () => {
            console.log('watched')
            for (const listener of this._dataListeners) {
                Vue.nextTick(() => {
                    listener.$forceUpdate()
                })
            }

        }, { deep: true })
    }

    _getMessages() {
        return this.messages
    }


    // 同 $t
    _t(key, locale, messages) {
        if (!key) return ''
        const res = this._translate(key, locale, messages)
        return res
    }

    // 单纯翻译, 即从 messages 对象中匹配
    _translate(key: string, locale, messages) {
        let last = key
        try {
            last = messages[locale]

            if(!last) throw new Error('错误的 locale 或没有对应 messages')
            const paths = key.split('.')

            paths.forEach(path => {
                last = last[path]
                if(last === undefined && path) throw new Error('key 没有匹配到对应 messages')
            })
            // if(last === undefined) 

        } catch (error) {
            console.warn(error)
            last = key // 保底
        }


        // 暂时只解 a.b.c 这种格式, a.b[1].c 以及插值语法等 以后考虑
        return last
    }
}


VueI18n.install = install